﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.SqlTypes;
using System.Drawing;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Xml;
using EIS.ClientUtility;
using EIS.DatabaseHelper;
using EIS.Obj;
using Ext.Connector.EIS;
using Janus.Windows.GridEX;
using Janus.Windows.Ribbon;

using TriState = Janus.Windows.ExplorerBar.TriState;

namespace EIS.ViewControl.Grid
{
    public partial class ViewGridDisplay : UserControl
    {
        public string FunctionID;
        public DataSet dataDs;
        private ViewGridController controller;

        public delegate void AddNewRecordDelegate();

        public AddNewRecordDelegate AddNewRecord;

        public ViewGridDisplay(string functionID)
        {

            FunctionID = functionID;
            InitializeComponent();
            controller = new ViewGridController(FunctionID, this);
            controller.InitSetDatePickers();


            AddNewRecord = new AddNewRecordDelegate(AddNewRecordMethod);
            controller.GetLocalData();


            FormatGrid();
            this.ribbonContextMenu1.SetContextMenu(this.gridEX1, true);
            GlobalVariable.Instance.CurrentViewHandler = this;

            foreach (var layout in GlobalVariable.Instance.LogonResult.Layout.ApplicationLayoutFromServer)
            {
                if (layout.FunctionID == this.FunctionID)
                {
                    this.labelCurrentViewName.Text = this.labelCurrentViewName.Text + layout.DisplayName;
                    break;
                }

            }

        }

        public void AddNewRecordMethod()
        {
            //TODO Change View
            if (ClientUtility.ClientConfig.Instance.RefreshViewAfterNewRecordComingIn)
            {
                controller.GetLocalData();
                FormatGrid();
            }
        }

        private void gridEX1_FormattingRow(object sender, Janus.Windows.GridEX.RowLoadEventArgs e)
        {

            //EISConstant.EISItemUnread
            var row = e.Row;
            if (row.DataRow == null) return;
            if (  (((DataRowView)row.DataRow).Row[2]).ToString() == "Y" )
            {
                if (  (((DataRowView)row.DataRow).Row[3]).ToString() == "3" )
                {
                    row.RowStyle = gridEX1.FormatStyles["UnreadRowErrorFormatStyle"];
                }
                if (  (((DataRowView)row.DataRow).Row[3]).ToString() == "2" )
                {
                    row.RowStyle = gridEX1.FormatStyles["UnreadRowWarningFormatStyle"];
                }
                if ((((DataRowView)row.DataRow).Row[3]).ToString() == "")
                {
                    row.RowStyle = gridEX1.FormatStyles["UnreadRowFormatStyle"]; ;
                }
            }
            else
            {
                if ((((DataRowView)row.DataRow).Row[3]).ToString() == "3")
                {
                    row.RowStyle = gridEX1.FormatStyles["ErrorRowStyle"];
                }
                if ((((DataRowView)row.DataRow).Row[3]).ToString() == "2")
                {
                    row.RowStyle = gridEX1.FormatStyles["WarningRowStyle"];
                }
                if ((((DataRowView)row.DataRow).Row[3]).ToString() == "")
                {
                    row.RowStyle = null;
                    
                }
            }
            
            gridEX1.CurrentLayoutChanged+=GridEx1OnCurrentLayoutChanged;
           // this.ResetRowCaptionsForReadUnread(this.gridEX1);
        }

        private void GridEx1OnCurrentLayoutChanged(object sender, EventArgs eventArgs)
        {
            GridEXLayout gridLayout = this.gridEX1.CurrentLayout;
        }

        public void FormatGrid(bool sizeColumns = true)
        {
            
            gridEX1.DataSource = dataDs.Tables[0].DefaultView;
            //gridEX1.DataMember = dataDs.Tables[0].TableName;

            gridEX1.EditMode = Janus.Windows.GridEX.EditMode.EditOff;
            gridEX1.ColumnAutoSizeMode = ColumnAutoSizeMode.AllCellsAndHeader;

            gridEX1.RetrieveStructure();
           
            gridEX1.ColumnSetHeaders = Janus.Windows.GridEX.InheritableBoolean.True;
            

            string layoutTableName = EISConstant.GetLayoutTableName(FunctionID);
            string schemaTableName = EISConstant.GetSchemaTableName(FunctionID);

            var dBHandler = new DBHandler();
            DataSet dsLayout = dBHandler.SelectSimple(layoutTableName);
            DataSet dsSchema = dBHandler.SelectSimple(schemaTableName);


            var colOrder = new string[dsLayout.Tables[0].Rows.Count];
            for (int i = 0; i < dsLayout.Tables[0].Rows.Count; i++)
            {
                //dsLayout.FieldName
                colOrder[i] = dsLayout.Tables[0].Rows[i][0].ToString();
            }

            GridExUtility.SetColumnOrder(colOrder, gridEX1.Tables[0]);
            for (int i = 0; i < dsSchema.Tables[0].Rows.Count; i++)
            {

                foreach (var fieldName in colOrder)
                {
                    if (fieldName == dsSchema.Tables[0].Rows[i][0].ToString())
                    {
                        gridEX1.Tables[0].Columns[fieldName].Caption = dsSchema.Tables[0].Rows[i][1].ToString();
                        break;
                    }
                }

            }

            if (sizeColumns)
            {
                var ds = dataDs;
                if (ds.Tables.Count == 0) return;
                var gar = this.gridEX1.CreateGraphics();
                foreach (GridEXColumn col in gridEX1.Tables[0].Columns)
                {
                    Font stringFont = new Font(this.gridEX1.Font.Name, this.gridEX1.Font.Size, FontStyle.Bold);

                    int columnMaxSize = MeasureDisplayStringWidth(gar, col.Caption, stringFont);
                    //int columnMaxSize = Convert.ToInt16(gridEX1.Font.SizeInPoints * col.Caption.Length); 


                    if (col.Visible)
                    {
                        foreach (DataRow row in ds.Tables[0].Rows)
                        {
                            int colWidth = MeasureDisplayStringWidth(gar, row[col.Key].ToString(), stringFont);
                            if (colWidth > columnMaxSize)
                                columnMaxSize = colWidth;
                        }
                        col.Width = columnMaxSize;
                    }
                    //col.AutoSize();
                }
            }
            
            SetLayout(this.controller.GetDefaultLayout());
        }
        static private int MeasureDisplayStringWidth(Graphics graphics, string text, Font font)
        {
            return  (int)(graphics.MeasureString(text, font).Width * 1.3 );
        }

        void gridEX1_RowDoubleClick(object sender, Janus.Windows.GridEX.RowActionEventArgs e)
        {

            Thread newThread = new Thread(new ParameterizedThreadStart(this.ThreadOpenRow));
            newThread.Start(e);
        }

        public void ThreadOpenRow(object e)
        {
            var par = (RowActionEventArgs) e;
            try
            {
                var connectorMeta = new ConnectorFactory.ConnectorFactory().GetConnector(this.FunctionID);
                if (connectorMeta != null)
                {
                    var method = connectorMeta.MethodInfo;
                    var instance = (Connector) connectorMeta.Instance;
                    if ( par.Row.DataRow != null)
                        method.Invoke(instance, new object[] {par.Row.DataRow});
                }
            }
            catch (Exception ex)
            {
                ShowErrorMessageBox.Show(ex.InnerException == null ? ex.Message : ex.InnerException.Message);

            }
            
        }
        public void OpenRow()
        {
            try
            {
                var connectorMeta = new ConnectorFactory.ConnectorFactory().GetConnector(this.FunctionID);
                if (connectorMeta != null)
                {
                    var method = connectorMeta.MethodInfo;
                    var instance = (Connector)connectorMeta.Instance;

                    method.Invoke(instance, new object[] { gridEX1.CurrentRow.DataRow });
                }
            }
            catch (Exception ex)
            {
                ShowErrorMessageBox.Show(ex.InnerException == null ? ex.Message : ex.InnerException.Message);

            }
             
        }
        public void ResetLayout()
        {
            controller.GetLocalData();
            FormatGrid();
        }
        private int GetChildrenUnreadNumber(GridEXRow row)
        {
            int total = 0;
            if ((row.DataRow != null) && (((DataRowView)row.DataRow).Row[EISConstant.EISItemUnread].ToString() == "Y"))

            {
                total = total + 1;

            }
            else
            {

                foreach (var childRow in row.GetChildRows())
                {
                    total = total + GetChildrenUnreadNumber(childRow);
                }    
            }
            
            return total;
        }

        private void ResetRowCaptionsForReadUnread(GridEX gridEx)
        {
            var rows = gridEx.GetRows();

            foreach (var gridExRow in rows)
            {
                var total = GetChildrenUnreadNumber(gridExRow);
                if (total != 0)
                {
                    gridExRow.GroupCaption = gridExRow.GroupCaption + " ( " + total.ToString() + " )";

                }
            }
        }

        private void gridEX1_GroupsChanged(object sender, GroupsChangedEventArgs e)
        {

        }
        private void gridEX1_LoadingRow(object sender, RowLoadEventArgs e)
        {
            // Unread?
/*            if ((string) ((DataRowView)e.Row.DataRow)[2] == "Y")
            {
                var style = e.Row.RowStyle;
                if (style != null)
                {
                    var usedFont = style.Font;
                    var newFont = new Font(usedFont.FontFamily, usedFont.Size, FontStyle.Bold);
                    style.Font = newFont;
                }
            }*/
            //TODO Group ->Unread Items, shall be recursive
        }

        private void gridEX1_CurrentCellChanging(object sender, CurrentCellChangingEventArgs e)
        {

            try
            {

                
                if (e.Row.CheckState == RowCheckState.Checked ) 
                if (gridEX1.Focused == false) return; //Prevent first row been selected and trigger the event. 
                if (e.Row == null) return;
                if (e.Row.DataRow == null) return;

                //First, copy current text to clipboard. 
                if (e.Row.Cells[e.Column.Key] != null) Clipboard.SetText(e.Row.Cells[e.Column.Key].Text);

                if (!ClientConfig.Instance.MarkReadAfterSelectRow) return;
                if ((((DataRowView)e.Row.DataRow)[EISConstant.EISItemUnread]).ToString() == "N") return;

                ((DataRowView)e.Row.DataRow).Row[EISConstant.EISItemUnread] = "N";
                e.Row.Format();
                var dtToUpdate = this.dataDs.Tables[0].Clone();
                var dr = dtToUpdate.NewRow();

                dr.ItemArray = ((DataRowView)e.Row.DataRow).Row.ItemArray;

                dr[2] = "N";
                dtToUpdate.Rows.Add(dr);
                controller.MarkReadUnread(dtToUpdate);

                
            }
            catch (Exception)
            {
                //Do nothing.
               
            }



        }

        public void MarkReadMethod()
        {

        }

        static void WaitSomeSeconds(int second)
        {
            Thread.Sleep(new TimeSpan(0,0,second));
        }

        public DateTime GetDatePickerFrom()
        {
            return this.dtPickerFrom.Value;
        }
        public DateTime GetDatePickerTo()
        {
            return this.dtPickerTo.Value;
        }
        public void SetDatePickerFrom(DateTime dateTime)
        {
            this.dtPickerFrom.Value = dateTime;
        }
        public void SetDatePickerTo(DateTime dateTime)
        {
            this.dtPickerTo.Value = dateTime;
        }

        private void btnLoadData_Click(object sender, EventArgs e)
        {
            this.controller.GetLocalData();
            this.FormatGrid();
        }

        private void lnkLabelToday_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            this.SetDatePickerFrom(new DateTime(DateTime.Now.Year,DateTime.Now.Month,DateTime.Now.Day,0,0,0));
            this.SetDatePickerTo(EISConstant.MaxDate);
            this.btnLoadData.PerformClick();
        }

        private void lnkLabelLast100_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            this.SetDatePickerTo(EISConstant.MaxDate);
            this.SetDatePickerFrom(DateTime.Now.AddDays(-100));
            this.btnLoadData.PerformClick();
        }

        private void lnkLabelAll_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            
            this.SetDatePickerFrom(EISConstant.MinDate);
            this.SetDatePickerTo(EISConstant.MaxDate);
            this.btnLoadData.PerformClick();
        }


        private void ribbonContextMenu1_CommandClick(object sender, CommandEventArgs e)
        {
            var dtToUpdate = this.dataDs.Tables[0].Clone();
            switch (e.Command.Key)
            {
                case "MarkAsRead":
                    
                    foreach (GridEXSelectedItem item in this.gridEX1.SelectedItems)
                    {
                        if (item.GetRow() == null) continue;
                        if (item.GetRow().DataRow == null) continue;
                        if ((((DataRowView)item.GetRow().DataRow)[EISConstant.EISItemUnread]).ToString() == "N") continue;
                        ((DataRowView)item.GetRow().DataRow)[EISConstant.EISItemUnread] = "N";
                        item.GetRow().Format();

                        var dr = dtToUpdate.NewRow();

                        dr.ItemArray = ((DataRowView)item.GetRow().DataRow).Row.ItemArray;

                        dr[2] = "N";
                        dtToUpdate.Rows.Add(dr);
                        
                    }
                    controller.MarkReadUnread(dtToUpdate);
                    
                    break;

                case "MarkAllAsRead":
                    controller.MarkAllAsRead();
                    break;
                case "MarkAsUnread":
                    dtToUpdate = this.dataDs.Tables[0].Clone();
                    foreach (GridEXSelectedItem item in this.gridEX1.SelectedItems)
                    {
                        if (item.GetRow() == null) continue;
                        if (item.GetRow().DataRow == null) continue;
                        if ((((DataRowView)item.GetRow().DataRow)[EISConstant.EISItemUnread]).ToString() == "Y") continue;
                        ((DataRowView)item.GetRow().DataRow)[EISConstant.EISItemUnread] = "Y";
                        item.GetRow().Format();

                        var dr = dtToUpdate.NewRow();

                        dr.ItemArray = ((DataRowView)item.GetRow().DataRow).Row.ItemArray;

                        dr[2] = "Y";
                        dtToUpdate.Rows.Add(dr);

                    }
                    controller.MarkReadUnread(dtToUpdate);
                    
                    break;

                case "CollapseGroups":
                    this.gridEX1.CollapseGroups();
                   // ResetRowCaptionsForReadUnread(this.gridEX1);
                    break;

                case "ExpandGroups":
                    this.gridEX1.ExpandGroups();
                    
                    break;
                    
                default:
                    break;
            }
        }

        private void ribbonContextMenu1_Opening(object sender, CancelEventArgs e)
        {
            var hasDataRow = false;
            foreach (GridEXSelectedItem item in this.gridEX1.SelectedItems)
            {
                if (item.GetRow() != null)
                {
                    if (item.GetRow().DataRow != null)
                    {
                        hasDataRow = true;
                        break;
                    }
                }
            }
            if (hasDataRow)
            {
                this.ribbonContextMenu1.Commands["MarkAsRead"].Enabled = true;
                this.ribbonContextMenu1.Commands["MarkAsUnread"].Enabled = true;
            }
            else
            {
                this.ribbonContextMenu1.Commands["MarkAsRead"].Enabled = false;
                this.ribbonContextMenu1.Commands["MarkAsUnread"].Enabled = false;

            }
            // if this.gridEX1.selecte
/*            if (item.GetRow() == null) return;
            if (item.GetRow().DataRow == null) return;*/
        }

        private void gridEX1_SortKeysChanged(object sender, EventArgs e)
        {
            this.gridEX1.MoveFirst();
        }

        public void GetLatestData()
        {
            try
            {
                BeginInvoke(this.AddNewRecord);
            }
            catch (Exception ex)
            {
                
                // Do nothing. 
            }
           
        }

        public void ExportToExcel()
        {
           
        }
        public string GetLayout()
        {
           GridEXLayout layout =  this.gridEX1.GetLayout();
           return layout.GetXmlString();
        }
        public void SetLayout(string layoutName)
        {   
            var dBHandler = new DBHandler();
            DataSet ds = dBHandler.SelectSimple(EISConstant.ClientLayoutTableName);
            if ( ds.Tables.Count == 0) return;

            foreach (DataRow dr in ds.Tables[0].Rows)
            {
                if (dr["FunctionID"].ToString() == GlobalVariable.Instance.CurrentFunctionID && dr["Layout"].ToString() == layoutName)
                {
                    GridEXLayout layout = GridEXLayout.FromXMLString(dr["LayoutXML"].ToString());
                   
                    this.gridEX1.LoadLayout(layout);
                    if (this.gridEX1.RowCount != 0 )this.gridEX1.Row = 0;
                    return;
                }
            }
           
        }
    }
}
